package save

import (
	"fmt"
	"gitee.com/alex_li/zangjingge/internal/db/rdb"
	"gitee.com/alex_li/zangjingge/internal/oss"
	"gitee.com/alex_li/zangjingge/internal/tools"
	"github.com/lishimeng/app-starter"
	"github.com/lishimeng/app-starter/persistence"
	"github.com/lishimeng/app-starter/server"
	"github.com/lishimeng/go-log"
	"math/rand"
	"time"
)

type Req struct {
	TempId string `json:"tempId"`
	Name   string `json:"name"`
	Bucket string `json:"bucket"`
}

type Resp struct {
	app.Response
	FileCode string `json:"fileCode"`
	FileName string `json:"fileName"`
}

func persistentFile(ctx server.Context) {

	var err error
	var req Req
	var resp Resp

	var reuse = false
	var bucketInfo rdb.BucketInfo
	var docInfo rdb.DocInfo

	err = ctx.C.ReadJSON(&req)
	if err != nil {
		resp.Code = 500
		ctx.Json(resp)
		return
	}
	log.Info("api: save_file. [bucket:%s]%s->%s", req.Bucket, req.TempId, req.Name)

	// 创建文件
	meta, err := oss.GetTempFileMeta(req.TempId)
	if err != nil {
		resp.Code = 500
		resp.Message = "temp_file not found " + req.Bucket
		ctx.Json(resp)
		return
	}
	//////////
	docCode := tools.GenMd5Code(fmt.Sprintf("doc_code_%d_%d", time.Now().UnixNano(), rand.Uint32()))
	docDigest := meta.Md5 + meta.Sha256

	// 数据库检查
	err = app.GetOrm().Transaction(func(tx persistence.TxContext) (er error) {
		// 检查bucket
		er = tx.Context.QueryTable(new(rdb.BucketInfo)).Filter("Code", req.Bucket).One(&bucketInfo)
		if err != nil {
			resp.Message = fmt.Sprintf("bucket not found:%s", req.Bucket)
			return
		}

		// 检查digest重复
		var tmpDocInfo rdb.DocInfo
		er = tx.Context.QueryTable(new(rdb.DocInfo)).Filter("Digest", docDigest).Limit(1).One(&tmpDocInfo)
		if er == nil {
			reuse = true
			// 重复, 复制一份数据
			copyDocInfo(docCode, req.Name, &docInfo, &tmpDocInfo)
			_, er = tx.Context.Insert(&docInfo)
			if er != nil {
				resp.Message = fmt.Sprintf("save file failed:[%s]%s", req.Bucket, req.TempId)
				return
			}
		} else {
			// 检查bucket
			er = tx.Context.QueryTable(new(rdb.BucketInfo)).Filter("Code", req.Bucket).One(&bucketInfo)
			if err != nil {
				resp.Message = fmt.Sprintf("bucket not found:%s", req.Bucket)
			}
			return
		}
		return
	})
	if err != nil {
		resp.Code = 500
		ctx.Json(resp)
		return
	}
	if !reuse {
		docInfo.Code = docCode
		docInfo.Name = req.Name
		docInfo.Bucket = bucketInfo.Code
		docInfo.Status = int(rdb.DocInfoStateInit)
		_, err = app.GetOrm().Context.Insert(&docInfo)
		if err != nil {
			log.Info(err)
			resp.Code = 500
			resp.Message = "create doc info failed"
			ctx.Json(resp)
			return
		}
		// 执行复制文件
		err = oss.ProcSaveFile(docInfo.Code, bucketInfo.Code, req.TempId)
		if err != nil {
			go func() {
				oss.ProcRemoveDocInfo(docInfo.Code)
			}()
			log.Info(err)
			resp.Code = 500
			resp.Message = "save file failed"
			ctx.Json(resp)
			return
		}
	}

	resp.Code = 200
	resp.FileCode = docCode
	resp.FileName = req.Name
	resp.Message = "success"
	ctx.Json(resp)
}

func copyDocInfo(code, name string, dst, src *rdb.DocInfo) {
	dst.Code = code
	dst.Digest = src.Digest
	dst.Bucket = src.Bucket
	dst.FilePath = src.FilePath
	dst.FileSize = src.FileSize
	dst.Ext = src.Ext
	dst.Status = int(rdb.DocInfoStateSave)
	dst.Name = name
}
